home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianComplexControls.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  19KB  |  739 lines

  1. /* ScianComplexControls.c: John R Murray August 23, 1990
  2.     Repository for all those weird controls with lots of little
  3.     thingamabobs that you can move around */
  4.  
  5. #include "Scian.h"
  6. #include "ScianTypes.h"
  7. #include "ScianColors.h"
  8. #include "ScianIDs.h"
  9. #include "ScianErrors.h"
  10. #include "ScianEvents.h"
  11. #include "ScianControls.h"
  12. #include "ScianButtons.h"
  13. #include "ScianComplexControls.h"
  14. #include "ScianMethods.h"
  15. #include "ScianArrays.h"
  16. #include "ScianWindows.h"
  17. #include "ScianObjWindows.h"
  18. #include "ScianScripts.h"
  19. #include "ScianDialogs.h"
  20. #include "ScianFontSystem.h"
  21. #include "ScianStyle.h"
  22. #include "ScianDraw.h"
  23. #include "ScianTextBoxes.h"
  24. #include "ScianSnap.h"
  25.  
  26. /* globals */
  27. ObjPtr    boundsControlClass;    /* Class of bounds control */
  28. ObjPtr    XYControlClass;        /* Class of XY controls */
  29.  
  30. #define LINELENGTH    15.0    /* length of border lines */
  31. #define BOUNDSBORDER    8.0    /* blank border around control stuff */
  32. #define LABELFONTFUDGE    1    /* fudge strings up (or <0 = down) to center */
  33.  
  34. ObjPtr    NewBoundsControl(left, right, bottom, top, label)
  35. int    left, right, bottom, top;
  36. char *label;
  37. /*Makes a new panel with bounds left, right, bottom, top, and label label*/
  38. {
  39.     real        values[6], hilites[6];
  40.     ObjPtr    valuesArray, hilitesArray;
  41.     ObjPtr      retVal;
  42.     ObjPtr      labelPtr;
  43.     ObjPtr      hilightPtr;
  44.  
  45.     values[0] = 0.0;
  46.     values[1] = 1.0;
  47.     values[2] = 0.0;
  48.     values[3] = 1.0;
  49.     values[4] = 0.0;
  50.     values[5] = 1.0;
  51.  
  52.     hilites[0] = false;
  53.     hilites[1] = false;
  54.     hilites[2] = false;
  55.     hilites[3] = false;
  56.     hilites[4] = false;
  57.     hilites[5] = false;
  58.  
  59.     valuesArray = NewRealArray(1, (long) 6);
  60.     hilitesArray = NewRealArray(1, (long) 6);
  61.     if (valuesArray && hilitesArray)
  62.     {
  63.     CArray2Array(valuesArray, values);
  64.     CArray2Array(hilitesArray, hilites);
  65.  
  66.     retVal = NewObject(boundsControlClass, 0);
  67.     Set2DIntBounds(retVal, left, right, bottom, top);
  68.     SetVar(retVal, VALUE, (ThingPtr) valuesArray);
  69.     SetVar(retVal, HIGHLIGHTED, (ThingPtr) hilitesArray);
  70.     labelPtr = NewString(label);
  71.     SetVar(retVal, NAME, labelPtr);
  72.     return retVal;
  73.     }
  74.     else
  75.     {
  76.         return NULLOBJ;
  77.     }
  78. }
  79.  
  80. void    SetBoundsControl(obj)
  81. ObjPtr obj;
  82. {
  83.     if (logging) LogControl(obj);
  84. }
  85.  
  86. /* Methods functions for Bounds Controls */
  87.  
  88. myMin(a,b)
  89. int a,b;
  90. {
  91.     return a < b ? a : b;
  92. }
  93.  
  94. int    DrawBoundsControl(theControl)
  95. ObjPtr    theControl;
  96. {
  97. #ifdef GRAPHICS
  98.     int left, right, bottom, top;
  99.     ObjPtr    theLabel;
  100.     char        *label;
  101.     ObjPtr    valuesArray, hilitesArray;
  102.     real        values[6], hilites[4];
  103.     real        xmin, xmax, ymin, ymax, zmin, zmax;
  104.     Coord       v[4][2];
  105.     real        xPos, yPos;
  106.     real        xRel, yRel;
  107.     real        fudgeScale;
  108.     real    recsize, recwidth, recdepth;
  109.  
  110.     /* get bounds, and draw control background */
  111.     if (!Get2DIntBounds(theControl, &left, &right, &bottom, &top))
  112.     {
  113.     return false;
  114.     }
  115.  
  116.     if (IsDrawingRestricted(left, right, bottom, top))
  117.     {
  118.     return false;
  119.     }
  120.  
  121.     valuesArray = GetFixedArrayVar("DrawBoundsControl",theControl,VALUE,1,6L);
  122.     hilitesArray = GetFixedArrayVar("DrawBoundsControl", theControl,
  123.                     HIGHLIGHTED, 1, 4L);
  124.     if (valuesArray && hilitesArray)
  125.     {
  126.         Array2CArray(values, valuesArray);
  127.         xmin = values[0];
  128.         xmax = values[1];
  129.         ymin = values[2];
  130.         ymax = values[3];
  131.         zmin = values[2];
  132.         zmax = values[3];
  133.  
  134.         Array2CArray(hilites, hilitesArray);
  135.     }
  136.     else
  137.     {
  138.         /* figure out a recovery? */
  139.         ReportError("DrawBoundsControl", "control missing bounds or values!\n");
  140.         return;
  141.     }
  142.     DrawRaisedRect(left, right, bottom, top, UIBACKGROUND);
  143.  
  144.     /* attempt to draw the control label */
  145.     theLabel = GetStringVar("DrawBoundsControl", theControl, NAME);
  146.     if (theLabel)
  147.     {
  148.  
  149.         label = GetString(theLabel);
  150.         SetUIColor(UITEXT);
  151.     SetUIFont(BUTTONFONT);
  152.     DrawAString(CENTERALIGN, (left + right) / 2,
  153.            (top+bottom)/2 + LABELFONTFUDGE - (int)BUTTONFONTSIZE/2,
  154.            label);
  155.     }
  156.  
  157.     SetUIColor(UITEXT);
  158.  
  159.     /* Draw the rest of the parts of the control */
  160.     recsize = myMin(right - left, top - bottom) - 2*(BOUNDSBORDER + LINELENGTH + 3);
  161.     recwidth = (int) ((2*recsize) / 3);
  162.     recdepth = (int) (recsize - recwidth);
  163.     /* Draw icon-like central figure, in center of control */
  164.     move2((int) ((right - left) / 2),(int) ((top - bottom) / 2));
  165.     rmv2((int) (recdepth / 2.0), (int) (recdepth / 2.0));
  166.     rdr2(-recwidth, 0.0);
  167.     rdr2(0.0, -recwidth);
  168.     rdr2(recwidth, 0.0);
  169.     rdr2(0.0, recwidth);
  170.     rdr2(recdepth, recdepth);
  171.     rdr2(-recwidth, 0.0);
  172.     rdr2(0.0, -recwidth);
  173.     rdr2(recwidth, 0.0);
  174.     rdr2(0.0, recwidth);
  175.     rmv2(-recwidth, 0.0);
  176.     rdr2(-recdepth, -recdepth);
  177.     rmv2(0.0, -recwidth);
  178.     rdr2(recdepth, recdepth);
  179.     rmv2(recwidth, 0.0);
  180.     rdr2(-recdepth, -recdepth);
  181.  
  182.     /* Draw bounds range lines. */
  183.  
  184. #endif /* GRAPHICS */
  185. }
  186.  
  187. int    PressBoundsControl(theControl, mouseX, mouseY, whichButton)
  188. ObjPtr        theControl;
  189. int    mouseX, mouseY;
  190. int        whichButton;
  191. {
  192. #ifdef INTERACTIVE
  193.     if (logging) LogControl(theControl);
  194. #endif /* INTERACTIVE */
  195. }
  196.  
  197. #define INITMINX    0.0
  198. #define INITMAXX    1.0
  199. #define INITX        0.5
  200. #define INITMINY    0.0
  201. #define INITMAXY    1.0
  202. #define INITY        0.5
  203.  
  204. ObjPtr    NewXYControl(left, right, bottom, top, name)
  205. int    left, right, bottom, top;
  206. char    *name;
  207. {
  208.     real        values[2], range[4];
  209.     ObjPtr    valuesArray, rangeArray;
  210.     ObjPtr      retVal;
  211.  
  212.     values[0] = INITX;
  213.     values[1] = INITY;
  214.  
  215.     range[0] = INITMINX;
  216.     range[1] = INITMAXX;
  217.     range[2] = INITMINY;
  218.     range[3] = INITMAXY;
  219.  
  220.     valuesArray = NewRealArray(1, 2L);
  221.     rangeArray = NewRealArray(1, 4L);
  222.     if (valuesArray && rangeArray)
  223.     {
  224.         CArray2Array(valuesArray, values);
  225.         CArray2Array(rangeArray, range);
  226.  
  227.         retVal = NewObject(XYControlClass, 0);
  228.     Set2DIntBounds(retVal, left, right, bottom, top);
  229.         SetVar(retVal, VALUE, valuesArray);
  230.     SetVar(retVal, RANGE, rangeArray);
  231.         SetVar(retVal, HIGHLIGHTED, NewInt(false));
  232.     SetVar(retVal, BACKGROUND, NewInt(UIPGREEN));
  233.         SetVar(retVal, NAME, NewString(name));
  234.         return retVal;
  235.     }
  236.     else
  237.     {
  238.     OMErr();
  239.         return NULLOBJ;
  240.     }
  241. }
  242.  
  243. #define XYCONTROLMARGIN (EDGE + 2)
  244. #define XYCONTROLKNOBSIZE 7
  245. #define XYCONTROLSLOP (SLOP + XYCONTROLMARGIN + XYCONTROLKNOBSIZE)
  246.  
  247.  
  248. ObjPtr    DrawXYControl(theControl)
  249. ObjPtr    theControl;
  250. {
  251. #ifdef GRAPHICS
  252.     int        left, right, bottom, top;
  253.     ObjPtr      theLabel;
  254.     char        *label;
  255.     ObjPtr      valuesArray, rangeArray, hilitesArray;
  256.     real        value[2], range[4];
  257.     real        xPos, yPos;
  258.     real        xRel, yRel;
  259.     real        fudgeScale;
  260.     real    recsize, recwidth, recdepth;
  261.  
  262.     /* get bounds, and draw control background */
  263.     if (!Get2DIntBounds(theControl, &left, &right, &bottom, &top))
  264.     {
  265.         return NULLOBJ;
  266.     }
  267.  
  268.     if (IsDrawingRestricted(left, right, bottom, top))
  269.     {
  270.     return ObjFalse;
  271.     }
  272.  
  273.     valuesArray = GetFixedArrayVar("DrawXYControl", theControl, VALUE, 1, 2L);
  274.     rangeArray = GetFixedArrayVar("DrawXYControl", theControl, RANGE, 1, 4L);
  275.     if (valuesArray && rangeArray)
  276.     {
  277.         Array2CArray(value, valuesArray);
  278.     Array2CArray(range, rangeArray);
  279.     }
  280.     else
  281.     {
  282.         /* figure out a recovery? */
  283.         ReportError("DrawXYControl", "control missing values");
  284.         return NULLOBJ;
  285.     }
  286.     /* draw the field */
  287.     DrawField(theControl);
  288.     DrawSunkenRect(left, right, bottom, top, UIPGREEN);
  289.  
  290.     left = left + XYCONTROLMARGIN + XYCONTROLKNOBSIZE;
  291.     right = right - XYCONTROLMARGIN - XYCONTROLKNOBSIZE;
  292.     bottom = bottom + XYCONTROLMARGIN + XYCONTROLKNOBSIZE;
  293.     top = top - XYCONTROLMARGIN - XYCONTROLKNOBSIZE;
  294.  
  295.     xPos = left + (right - left) * (value[0]-range[0])/(range[1]-range[0]);
  296.     yPos = bottom + (top - bottom) * (value[1]-range[2])/(range[3]-range[2]);
  297.  
  298.     /* draw the thingamabob in the middle, for now */
  299.     DrawRaisedRect(xPos - XYCONTROLKNOBSIZE, xPos + XYCONTROLKNOBSIZE,
  300.     yPos - XYCONTROLKNOBSIZE, yPos + XYCONTROLKNOBSIZE,
  301.     GetPredicate(theControl, HIGHLIGHTED) ? UIHIBACKGROUND : UIBACKGROUND);
  302. #endif /* GRAPHICS */
  303. }
  304.  
  305. ObjPtr PressXYControl(object, mouseX, mouseY, flags)
  306. ObjPtr object;
  307. int mouseX, mouseY;
  308. long flags;
  309. /*Track a click in an XY control.  Double-click snaps to corner, edge, or center*/
  310. {
  311. #ifdef INTERACTIVE
  312.     real left, right, bottom, top;
  313.     int li, ri, bi, ti;
  314.     ObjPtr valueArray, rangeArray;
  315.     real value[2], range[4];
  316.     real oldv0, oldv1;            /* old values of value[0] and [1] */
  317.     int lastX, lastY;            /*Last X and Y mouse position*/
  318.     Bool dontTrack, alwaysChange;    /*True iff don't track, always change*/
  319.  
  320.     if ( ! Get2DIntBounds(object, &li, &ri, &bi, &ti))
  321.     {
  322. #if 0
  323.     I think Eric changed this in Austin
  324.     GetWindowBounds(&li, &ri, &bi, &ti);
  325. #else
  326.     return ObjFalse;
  327. #endif
  328.  
  329.     }
  330.     left = li;
  331.     right = ri;
  332.     bottom = bi;
  333.     top = ti;
  334.  
  335.     if (mouseX < left || mouseX > right || mouseY < bottom || mouseY > top)
  336.     {
  337.     return ObjFalse;
  338.     }
  339.  
  340.     if (TOOL(flags) == T_HELP)
  341.     {
  342.     ContextHelp(object);
  343.     return ObjTrue;
  344.     }
  345.  
  346.     /* it's really a press, and not a helpclick, so.. */
  347.     SaveForUndo(object);
  348.  
  349.     left = left + XYCONTROLMARGIN + XYCONTROLKNOBSIZE;
  350.     right = right - XYCONTROLMARGIN - XYCONTROLKNOBSIZE;
  351.     bottom = bottom + XYCONTROLMARGIN + XYCONTROLKNOBSIZE;
  352.     top = top - XYCONTROLMARGIN - XYCONTROLKNOBSIZE;
  353.  
  354.     /*Get the current value of the control*/
  355.     valueArray = GetFixedArrayVar("PressXYControl", object, VALUE, 1, 2L);
  356.     rangeArray = GetFixedArrayVar("PressXYControl", object, RANGE, 1, 4L);
  357.     if (!valueArray || !rangeArray)
  358.     { 
  359.     return ObjFalse;
  360.     }
  361.     Array2CArray(value, valueArray);
  362.     Array2CArray(range, rangeArray);
  363.  
  364.     oldv0 = value[0];
  365.     oldv1 = value[1];
  366.     lastX = value[0];
  367.     lastY = value[1];
  368.  
  369.     if (flags & F_DOUBLECLICK)
  370.     {
  371.     FuncTyp method;
  372.     /*Snap current value to closest corner, side, or center*/
  373.     if ((mouseX - left) / (right - left)  < 0.25)
  374.     {
  375.         value[0] = range[0];
  376.     }
  377.     else if ((mouseX - left) / (right - left) > 0.75)
  378.     {
  379.         value[0] = range[1];
  380.     }
  381.     else
  382.     {
  383.         value[0] = (range[1] + range[0]) / 2;
  384.     }
  385.  
  386.     if ((mouseY - bottom) / (top - bottom) < 0.25)
  387.     {
  388.         value[1] = range[2];
  389.     }
  390.     else if ((mouseY - bottom) / (top - bottom) > 0.75)
  391.     {
  392.         value[1] = range[3];
  393.     }
  394.     else
  395.     {
  396.         value[1] = (range[3] + range[2]) / 2;
  397.     }
  398.  
  399.     valueArray = NewRealArray(1, 2L);
  400.     CArray2Array(valueArray, value);
  401.     SetVar(object, VALUE, valueArray);
  402.     DrawMe(object);
  403.     ChangedValue(object);
  404.     return ObjTrue;
  405.     }
  406.     dontTrack = GetPredicate(object, TRACKNOT);
  407.     alwaysChange = GetPredicate(object, ALWAYSCHANGE);
  408.  
  409.     SetVar(object, HIGHLIGHTED, NewInt(true));
  410.  
  411.     if (flags & F_SHIFTDOWN)
  412.     {
  413.     lastX = mouseX;
  414.     lastY = mouseY;
  415.  
  416.     SetVar(object, HIGHLIGHTED, NewInt(true));
  417.     DrawMe(object);
  418.     while (abs(lastX - mouseX) < 3 && abs(lastY - mouseY) < 3)
  419.     {
  420.         if (!Mouse(&mouseX, &mouseY))
  421.         return ObjTrue;
  422.         if (alwaysChange && !dontTrack)
  423.         {
  424.         ChangedValue(object);
  425.         }
  426.     }
  427.     if (abs(lastX - mouseX) > abs(lastY - mouseY)) /* X axis only */
  428.     {
  429.         while (Mouse(&mouseX, &mouseY))
  430.         {
  431.         if (mouseX != lastX)
  432.         {
  433.             lastX = mouseX;
  434.  
  435.             if (mouseX < left - XYCONTROLSLOP
  436.             || mouseX > right + XYCONTROLSLOP
  437.             || mouseY < bottom - XYCONTROLSLOP
  438.             || mouseY > top + XYCONTROLSLOP)
  439.             {
  440.             /* outside slop rectangle, restore old values */
  441.             value[0] = oldv0;
  442.             value[1] = oldv1;
  443.             SetVar(object, HIGHLIGHTED, NewInt(false));
  444.             }
  445.             else /* calculate new values based on mouse position */
  446.             {
  447.             value[0] = range[0] + ((mouseX - left) / (right - left)) * (range[1] - range[0]);
  448.             if (value[0] < range[0]) value[0] = range[0];
  449.             if (value[0] > range[1]) value[0] = range[1];
  450.             SetVar(object, HIGHLIGHTED, NewInt(true));
  451.             }
  452.             valueArray = NewRealArray(1, 2L);
  453.             CArray2Array(valueArray, value);
  454.             SetVar(object, VALUE, valueArray);
  455.             DrawMe(object);
  456.             if (!dontTrack)
  457.             {
  458.             ChangedValue(object);
  459.             }            
  460.         }
  461.         else if (alwaysChange && !dontTrack)
  462.         {
  463.             ChangedValue(object);
  464.         }
  465.         }
  466.     }
  467.     else /* Y axis only */
  468.     {
  469.         while (Mouse(&mouseX, &mouseY))
  470.         {
  471.         if (mouseY != lastY)
  472.         {
  473.             lastY = mouseY;
  474.  
  475.             if (mouseX < left - XYCONTROLSLOP
  476.             || mouseX > right + XYCONTROLSLOP
  477.             || mouseY < bottom - XYCONTROLSLOP
  478.             || mouseY > top + XYCONTROLSLOP)
  479.             {
  480.             /* outside slop rectangle, restore old values */
  481.             value[0] = oldv0;
  482.             value[1] = oldv1;
  483.             SetVar(object, HIGHLIGHTED, NewInt(false));
  484.             }
  485.             else /* calculate new values based on mouse position */
  486.             {
  487.             value[1] = range[2] + ((mouseY - bottom) / (top - bottom)) * (range[3] - range[2]);
  488.             if (value[1] < range[2]) value[1] = range[2];
  489.             if (value[1] > range[3]) value[1] = range[3];
  490.             SetVar(object, HIGHLIGHTED, NewInt(true));
  491.             }
  492.             valueArray = NewRealArray(1, 2L);
  493.             CArray2Array(valueArray, value);
  494.             SetVar(object, VALUE, valueArray);
  495.             DrawMe(object);
  496.             if (!dontTrack)
  497.             {
  498.             ChangedValue(object);
  499.             }            
  500.         }
  501.         else if (alwaysChange && !dontTrack)
  502.         {
  503.             ChangedValue(object);
  504.         }
  505.         }
  506.     }
  507.     }
  508.     else /* free tracking on X and Y axes */
  509.     {
  510.     while (Mouse(&mouseX, &mouseY))
  511.     {
  512.         if (mouseX != lastX || mouseY != lastY)
  513.         {
  514.         lastX = mouseX;
  515.         lastY = mouseY;
  516.  
  517.         if (mouseX < left - XYCONTROLSLOP
  518.             || mouseX > right + XYCONTROLSLOP
  519.             || mouseY < bottom - XYCONTROLSLOP
  520.             || mouseY > top + XYCONTROLSLOP)
  521.         {
  522.             /* outside slop rectangle, restore old values */
  523.             value[0] = oldv0;
  524.             value[1] = oldv1;
  525.             SetVar(object, HIGHLIGHTED, NewInt(false));
  526.         }
  527.         else /* calculate new values based on mouse position */
  528.         {
  529.             value[0] = range[0] + ((mouseX - left) / (right - left)) * (range[1] - range[0]);
  530.             if (value[0] < range[0]) value[0] = range[0];
  531.             if (value[0] > range[1]) value[0] = range[1];
  532.             value[1] = range[2] + ((mouseY - bottom) / (top - bottom)) * (range[3] - range[2]);
  533.             if (value[1] < range[2]) value[1] = range[2];
  534.             if (value[1] > range[3]) value[1] = range[3];
  535.             SetVar(object, HIGHLIGHTED, NewInt(true));
  536.         }
  537.  
  538.         valueArray = NewRealArray(1, 2L);
  539.         CArray2Array(valueArray, value);
  540.         SetVar(object, VALUE, valueArray);
  541.         DrawMe(object);
  542.         if (!dontTrack)
  543.         {
  544.             ChangedValue(object);
  545.         }
  546.         }
  547.         else if (alwaysChange && !dontTrack)
  548.         {
  549.         DrawMe(object);
  550.         ChangedValue(object);
  551.         }
  552.     }
  553.     }
  554.     if (dontTrack)
  555.     {
  556.     ChangedValue(object);
  557.     }
  558.     SetVar(object, HIGHLIGHTED, NewInt(false));
  559.     ImInvalid(object);
  560.     if (logging) LogControl(object);
  561.     return ObjTrue;
  562. #endif /* INTERACTIVE */
  563. }
  564.  
  565. #ifdef PROTO
  566. Bool SetXYControlLimits(ObjPtr theControl, real minX, real maxX,
  567.                        real minY, real maxY)
  568. #else
  569. Bool SetXYControlLimits(theControl, minX, maxX, minY, maxY)
  570. ObjPtr theControl;
  571. real minX, maxX, minY, maxY;
  572. #endif
  573. {
  574.     ObjPtr    valuesArray, rangeArray;
  575.     real    values[2], range[4];
  576.     Bool    changed = false;
  577.  
  578.     if (minX >= maxX || minY >= maxY)
  579.     {
  580.     /* give up! */
  581.     ReportError("SetXYControlLimits", "error in XY control range\n");
  582.     return false;
  583.     }
  584.  
  585.     valuesArray = GetFixedArrayVar("SetXYControlLimits", theControl, VALUE, 1, 2L);
  586.     if (!valuesArray)
  587.     {
  588.     return false;
  589.     }
  590.     range[0] = minX;
  591.     range[1] = maxX;
  592.     range[2] = minY;
  593.     range[3] = maxY;
  594.     rangeArray = NewRealArray (1, 4L);
  595.     CArray2Array(rangeArray, range);
  596.     SetVar(theControl, RANGE, rangeArray);
  597.  
  598.     /* adjust slider values if they're now out of range */
  599.     Array2CArray(values, valuesArray);
  600.     if (values[0]<minX || values[0]>maxX || values[1]<minY || values[1]>maxY)
  601.     {
  602.     changed = true;
  603.     values[0] = values[0]<minX ? minX : (values[0]>maxX ? maxX : values[0]);
  604.     values[1] = values[1]<minY ? minY : (values[1]>maxY ? maxY : values[1]);
  605.     valuesArray = NewRealArray(1, 2L);
  606.     CArray2Array(valuesArray, values);
  607.     SetVar(theControl, VALUE, valuesArray);
  608.     }
  609.  
  610.     ImInvalid(theControl);
  611.     if (changed)
  612.     {
  613.     ChangedValue(theControl);
  614.     }
  615.  
  616.     return true;
  617. }
  618.  
  619. Bool GetXYControlLimits(obj, minX, maxX, minY, maxY)
  620. ObjPtr obj;
  621. real *minX, *minY, *maxX, *maxY;
  622. {
  623.     ObjPtr rangeArray;
  624.     real range[4];
  625.  
  626.     rangeArray = GetFixedArrayVar("GetXYControlLimits", obj, RANGE, 1, 4L);
  627.     if (!rangeArray)
  628.     {
  629.     return false;
  630.     }
  631.     Array2CArray(range, rangeArray);
  632.  
  633.     *minX = range[0];
  634.     *maxX = range[1];
  635.     *minY = range[2];
  636.     *maxY = range[3];
  637.     return true;
  638. }
  639.  
  640. #ifdef PROTO
  641. Bool SetXYControlValue(ObjPtr obj, real xvalue, real yvalue)
  642. #else
  643. Bool SetXYControlValue(obj, xvalue, yvalue)
  644. ObjPtr obj;
  645. real xvalue, yvalue;
  646. #endif
  647. /* sets values of 2D control. Non-method version */
  648. {
  649.     ObjPtr valuesArray, rangeArray;
  650.     real value[2], range[4];
  651.     real oldv0, oldv1;
  652.  
  653.     valuesArray = GetFixedArrayVar("SetXYControlValue", obj, VALUE, 1, 2L);
  654.     rangeArray = GetFixedArrayVar("SetXYControlValue", obj, RANGE, 1, 4L);
  655.     if (!valuesArray || !rangeArray)
  656.     {
  657.     ReportError("SetXYControlValue", "error in values or range array");
  658.     return false;
  659.     }
  660.     Array2CArray(value, valuesArray);
  661.     Array2CArray(range, rangeArray);
  662.  
  663.     oldv0 = value[0];
  664.     oldv1 = value[1];
  665.     if (xvalue < range[0])
  666.     value[0] = range[0];
  667.     else if (xvalue > range[1])
  668.     value [0] = range[1];
  669.     else
  670.     value[0] = xvalue;
  671.  
  672.     if (yvalue < range[2])
  673.     value[1] = range[2];
  674.     else if (yvalue > range[3])
  675.     value[1] = range[3];
  676.     else
  677.     value[1] = yvalue;
  678.  
  679.     valuesArray = NewRealArray(1, 2L);
  680.     CArray2Array(valuesArray, value);
  681.     SetVar(obj, VALUE, valuesArray);
  682.     if (oldv0 != value[0] || oldv1 != value[1])
  683.     {
  684.     ImInvalid(obj);
  685.     ChangedValue(obj);
  686.     }
  687.     if (logging) LogControl(obj);
  688.     return true;
  689. }
  690.  
  691. Bool GetXYControlValue(obj, xvalue, yvalue)
  692. ObjPtr obj;
  693. real *xvalue, *yvalue;
  694. {
  695.     ObjPtr valuesArray;
  696.     real value[2];
  697.  
  698.     valuesArray = GetFixedArrayVar("GetXYControlValue", obj, VALUE, 1, 2L);
  699.     if (!valuesArray)
  700.     {
  701.     return false;
  702.     }
  703.     Array2CArray(value, valuesArray);
  704.  
  705.     *xvalue = value[0];
  706.     *yvalue = value[1];
  707.     return true;
  708. }
  709.  
  710. ObjPtr GetXYControlObjValue(obj)
  711. ObjPtr obj;
  712. {
  713.     return GetVar(obj, VALUE);
  714. }
  715.  
  716. void    InitXYControls()
  717. {
  718.     XYControlClass = NewObject(controlClass, 0);
  719.     AddToReferenceList((ThingPtr) XYControlClass);
  720.     SetMethod(XYControlClass, DRAW, DrawXYControl);
  721.     SetMethod(XYControlClass, PRESS, PressXYControl);
  722. /* These are incorrect until FuncTyp gets redefined
  723.     SetMethod(XYControlClass, SETVAL, SetXYControlObjValue);
  724. */
  725.     SetMethod(XYControlClass, GETVAL, GetXYControlObjValue);
  726.     SetVar(XYControlClass, TYPESTRING, NewString("control"));
  727.     SetVar(XYControlClass, HELPSTRING, NewString(
  728. "This is a two-valued slider. By clicking and dragging the \"thumb\" in \
  729. the control, you can change one or both of the values. You can change only \
  730. one of the values by holding the Shift key down while you click and drag \
  731. the \"thumb\". If you double-click it, the values will snap to the closest \
  732. one of maximum, minimum or middle value of the range for each value."));
  733. }
  734.  
  735. void KillXYControls()
  736. {
  737.     RemoveFromReferenceList(XYControlClass);
  738. }
  739.